﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerControl : MonoBehaviour
{
    private Rigidbody2D rb;
    private BoxCollider2D boxColl;

    [Header("移动参数")]
    public float speed =8f;
    public float crouchSpeedDivisor = 3f;

    [Header("跳跃参数")]
    private float jumpForce = 16f;
    private float jumpHoldForce = 20.8f;             //蓄力力度
    private float crouchJumpBoost = 32f;
    private float hangingJumpForce = 18f;
    public float jumpHoldDuration;   //蓄力持续值

    private float jumpHoldTime;             //蓄力时间


    [Header("人物状态")]
    public bool isCrouch;
    public bool isOnGround;
    public bool isJump;
    public bool isHeadBlocked;
    public bool isHanging;

    [Header("环境监测")]
    public LayerMask groundLayer;       //实物碰撞层
    public float footOffset = 0.4f;
    public float headClearance = 0.5f;
    public float groundDistance = 0.2f;

    public float eyeHeight = 1.5f;
    public float grabDistance = 0.4f;
    public float reachOffset = 0.7f;
    private float playerHeight;


    //按键设置
    private bool jumpPressed;
    private bool crouchPressed;
    private bool jumpHeld;
    private bool crouchHeld;


    //碰撞体尺寸
    Vector2 colliderStandSize;
    Vector2 colliderStandOffset;
    Vector2 colliderCrouchSize;
    Vector2 colliderCrouchOffset;

    public float xVelocity;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        boxColl = GetComponent<BoxCollider2D>();

        playerHeight = boxColl.size.y;

        colliderStandSize = boxColl.size;       //站立碰撞体大小
        colliderStandOffset = boxColl.offset;   //站立碰撞体偏移值
        colliderCrouchSize = new Vector2(boxColl.size.x , boxColl.size.y / 2f);
        colliderCrouchOffset = new Vector2(boxColl.offset.x, boxColl.offset.y / 2f);
    }

    void Update()
    {
        if (GameManager.GameOver()) return;

        jumpPressed = Input.GetButtonDown("Jump");
        jumpHeld = Input.GetButton("Jump");
        crouchHeld = Input.GetButton("Crouch");
        crouchPressed = Input.GetButtonDown("Crouch");
        MidAirMovement();
    }

    private void FixedUpdate()
    {
        if (GameManager.GameOver()) return;

        PhysicsCheck();
        PlayMovement();
    }

    private void PhysicsCheck() //物理监测
    {
        //如果射线监测到物体返回true
        RaycastHit2D leftCheck = Raycast(new Vector2(-footOffset, 0f), Vector2.down, groundDistance, groundLayer);
        RaycastHit2D rightCheck = Raycast(new Vector2(footOffset, 0f), Vector2.down, groundDistance, groundLayer);

        if (leftCheck || rightCheck)
            isOnGround = true;
        else
            isOnGround = false;

        RaycastHit2D headCheck = Raycast(new Vector2(0f,boxColl.size.y),Vector2.up,headClearance,groundLayer);

        if (headCheck)
            isHeadBlocked = true;
        else
            isHeadBlocked = false;

        float direction = transform.localScale.x;
        Vector2 grabDir = new Vector2(direction,0f);    //射线方向与人物方向一致

        RaycastHit2D blockedCheck = Raycast(new Vector2(footOffset*direction, playerHeight),grabDir,grabDistance,groundLayer);
        RaycastHit2D wallCheck = Raycast(new Vector2(footOffset * direction, eyeHeight), grabDir, grabDistance, groundLayer);
        RaycastHit2D ledgeCheck = Raycast(new Vector2(reachOffset* direction, playerHeight),Vector2.down,grabDistance,groundLayer);

        if (!isOnGround && wallCheck && ledgeCheck&& rb.velocity.y<0 && !blockedCheck)
        {
            Vector3 pos = transform.position;
            //为人物悬挂墙壁的射线检定清除空隙,使人物贴合墙壁
            pos.x += (wallCheck.distance - 0.05f) * direction;
            pos.y -= ledgeCheck.distance;
            transform.position = pos;

            rb.bodyType = RigidbodyType2D.Static;
            isHanging = true;
        }
    }

    void PlayMovement() //角色移动
    {
        if (isHanging) return;

        if (crouchHeld && !isCrouch && isOnGround)
            Crouch();
        else if (!crouchHeld && isCrouch && !isHeadBlocked)
            StandUp();
        else if (!isOnGround && isCrouch)
            StandUp();

        FilpDirction();

        if (isCrouch)//下蹲速度减慢
        {
            xVelocity /= crouchSpeedDivisor;
        }

        xVelocity = Input.GetAxis("Horizontal");//-1f到1f 键盘停止输入时值为0,所以摩擦力为0也不会惯性式滑动

        rb.velocity = new Vector2(xVelocity * speed , rb.velocity.y);
    }

    void FilpDirction() //面向判断
    {
        if (xVelocity < 0)
        {
            transform.localScale = new Vector3(-1,1,1);
        }
        if (xVelocity > 0)
        {
            transform.localScale = new Vector3(1, 1,1);
        }
    }

    void MidAirMovement() //跳跃
    {
        if (isHanging)//悬挂状态
        {
            if (jumpPressed)
            {
                rb.bodyType = RigidbodyType2D.Dynamic;
                //rb.AddForce(new Vector2(0f, hangingJumpForce* Time.deltaTime), ForceMode2D.Impulse);
                rb.velocity = new Vector2(rb.velocity.x, hangingJumpForce);
                isHanging = false;
            }
            if (crouchPressed)
            {
                rb.bodyType = RigidbodyType2D.Dynamic;
                isHanging = false;
            }
        }
        if (isOnGround && jumpPressed && !isJump && !isHeadBlocked)//正常跳跃
        {
            if (isCrouch && isOnGround )//下蹲跳
            {
                StandUp();
                //rb.AddForce(new Vector2(0f, crouchJumpBoost * Time.deltaTime), ForceMode2D.Impulse);
                rb.velocity = new Vector2(rb.velocity.x, crouchJumpBoost);
            }

            isOnGround = false;
            isJump = true;
            jumpHoldTime = Time.time + jumpHoldDuration;
            //rb.AddForce(new Vector2(0f, jumpForce* Time.deltaTime), ForceMode2D.Impulse);
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);

            AudioManager.PlayJumpAudio();
        }
        else if(isJump)
        {
            if (jumpHeld)//蓄力跳
            {
                //rb.AddForce(new Vector2(0f, jumpHoldForce * Time.deltaTime), ForceMode2D.Impulse);
                rb.velocity = new Vector2(rb.velocity.x, jumpHoldForce);
            }

            if (jumpHoldTime < Time.time)//结束跳跃
            {
                isJump = false;
            }
        }
    }

    void Crouch() //下蹲
    {
        boxColl.size = colliderCrouchSize;
        boxColl.offset = colliderCrouchOffset;
        isCrouch = true;
    }

    void StandUp() //站立
    {
        boxColl.size = colliderStandSize;
        boxColl.offset = colliderStandOffset;
        isCrouch = false;
    }

    RaycastHit2D Raycast(Vector2 offset, Vector2 rayDirction ,float length, LayerMask layer) //射线监测
    {
        Vector2 pos = transform.position;

        RaycastHit2D hit = Physics2D.Raycast(pos + offset, rayDirction, length, layer);//参数:监测点坐标,方向,长度,碰撞层

        Color color = hit ? Color.red : Color.green;

        Debug.DrawRay(pos+offset,rayDirction * length,color);

        return hit;
    }
}
